package com.pt5.pthouduan.entity;

import com.pt5.pthouduan.mapper.UserMapper;
import com.pt5.pthouduan.service.impl.updatePeerStatsService;
import com.turn.ttorrent.common.PeerUID;
import com.turn.ttorrent.common.protocol.AnnounceRequestMessage;
import com.turn.ttorrent.tracker.TrackedPeer;
import com.turn.ttorrent.tracker.TrackedTorrent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.sql.DataSource;
import java.io.UnsupportedEncodingException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

//import static com.pt5.pthouduan.entity.CustomTorrentsRepository.hexToBytes;

public class TrackeredTorrentWithStats extends TrackedTorrent{
    private static final Logger logger = LoggerFactory.getLogger(TrackeredTorrentWithStats.class);
    private final ConcurrentMap<PeerUID,long[]> lastStats = new ConcurrentHashMap<>();
    private final DataSource dataSource;
    private final String passkey;
    private final updatePeerStatsService statsService;
    public TrackeredTorrentWithStats(byte[] infoHash, DataSource datasource, String passkey, updatePeerStatsService statsService){
        super(infoHash);
        this.dataSource = datasource;
        this.passkey = passkey;
        this.statsService = statsService;
    }

    @Override
    public TrackedPeer update(AnnounceRequestMessage.RequestEvent event, ByteBuffer peerId, String hexPeerId, String ip, int port, long uploaded, long downloaded, long left)
            throws UnsupportedEncodingException{
        System.out.println("Peer update triggered!");
        String passkey = PasskeyContext.getPasskey();
        System.out.println("AcceptedPasskey: " + passkey);
        PeerUID peerUID = new PeerUID(new InetSocketAddress(ip, port),this.getHexInfoHash());
        long[] last = lastStats.getOrDefault(peerUID, new long[]{0L,0L});
        long deltaUpload = Math.max(0,uploaded - last[0]);
        long deltaDownloaded = Math.max(0,downloaded - last[1]);
        lastStats.put(peerUID,new long[]{uploaded,downloaded});
        //updatePeerStatsInDB(this.getHexInfoHash(),ip,port,hexPeerId,uploaded,downloaded,deltaUpload,deltaDownloaded,passkey);
        try {
            // 调用服务层更新统计
            statsService.updatePeerStatsInDB(
                    this.getHexInfoHash(),
                    ip,
                    port,
                    hexPeerId,
                    uploaded,
                    downloaded,
                    deltaUpload,
                    deltaDownloaded,
                    passkey,
                    event.name(), // 加上 event 类型
                    left // 用于判断是否完成下载
            );
            // 新增：更新 Torrent 的最晚做种时间
            updateLastSeedTimeInDB(this.getHexInfoHash().toLowerCase());
        } catch (Exception e) {
            // 使用日志框架记录错误
            logger.error("Failed to update peer stats", e);
            throw new RuntimeException("Failed to update peer stats", e); // 可根据需求决定是否抛出异常
        }
        System.out.println("接收到 peer announce: " + ip + ":" + port + ", uploaded=" + uploaded + ", downloaded=" + downloaded);
        logger.debug("Peer updated: {}:{} (up={}, down={}, Δup={}, Δdown={})",
                ip, port, uploaded, downloaded, deltaUpload, deltaDownloaded);
        return super.update(event,peerId,hexPeerId,ip,port,uploaded,downloaded,left);
    }
    // 新增方法：更新 Torrent 的最晚做种时间
    private void updateLastSeedTimeInDB(String infoHash) {
        String sql = "UPDATE torrent SET last_seed = now() WHERE info_hash = ?";
        try (Connection conn = dataSource.getConnection();
             PreparedStatement stmt = conn.prepareStatement(sql)) {
            System.out.println("Current info_hash: " + infoHash);

            stmt.setString(1, infoHash);
            stmt.executeUpdate();
            System.out.println("更新最后做种时间");

        } catch (SQLException e) {
            logger.error("Failed to update last_seed_time for info_hash: {}", infoHash, e);
        }
    }

//package com.pt5.pthouduan.entity;
//
//import com.pt5.pthouduan.mapper.UserMapper;
//import com.pt5.pthouduan.service.impl.updatePeerStatsService;
//import com.turn.ttorrent.common.PeerUID;
//import com.turn.ttorrent.common.protocol.AnnounceRequestMessage;
//import com.turn.ttorrent.tracker.TrackedPeer;
//import com.turn.ttorrent.tracker.TrackedTorrent;
//import org.slf4j.Logger;
//import org.slf4j.LoggerFactory;
//
//import javax.sql.DataSource;
//import java.io.UnsupportedEncodingException;
//import java.net.InetSocketAddress;
//import java.nio.ByteBuffer;
//import java.sql.Connection;
//import java.sql.PreparedStatement;
//import java.sql.SQLException;
//import java.util.concurrent.ConcurrentHashMap;
//import java.util.concurrent.ConcurrentMap;
//
////import static com.pt5.pthouduan.entity.CustomTorrentsRepository.hexToBytes;
//
//public class TrackeredTorrentWithStats extends TrackedTorrent{
//    private static final Logger logger = LoggerFactory.getLogger(TrackeredTorrentWithStats.class);
//    private final ConcurrentMap<PeerUID,long[]> lastStats = new ConcurrentHashMap<>();
//    private final DataSource dataSource;
//    private final String passkey;
//    private final updatePeerStatsService statsService;
//    public TrackeredTorrentWithStats(byte[] infoHash, DataSource datasource, String passkey, updatePeerStatsService statsService){
//        super(infoHash);
//        this.dataSource = datasource;
//        this.passkey = passkey;
//        this.statsService = statsService;
//    }
//
//    @Override
//    public TrackedPeer update(AnnounceRequestMessage.RequestEvent event, ByteBuffer peerId, String hexPeerId, String ip, int port, long uploaded, long downloaded, long left)
//        throws UnsupportedEncodingException{
//        System.out.println("Peer update triggered!");
//        String passkey = PasskeyContext.getPasskey();
//        System.out.println("AcceptedPasskey: " + passkey);
//        PeerUID peerUID = new PeerUID(new InetSocketAddress(ip, port),this.getHexInfoHash());
//        long[] last = lastStats.getOrDefault(peerUID, new long[]{0L,0L});
//        long deltaUpload = Math.max(0,uploaded - last[0]);
//        long deltaDownloaded = Math.max(0,downloaded - last[1]);
//        lastStats.put(peerUID,new long[]{uploaded,downloaded});
//        //updatePeerStatsInDB(this.getHexInfoHash(),ip,port,hexPeerId,uploaded,downloaded,deltaUpload,deltaDownloaded,passkey);
//        try {
//            // 调用服务层更新统计
//            statsService.updatePeerStatsInDB(
//                    this.getHexInfoHash(),
//                    ip,
//                    port,
//                    hexPeerId,
//                    uploaded,
//                    downloaded,
//                    deltaUpload,
//                    deltaDownloaded,
//                    passkey
//            );
//            // 新增：更新 Torrent 的最晚做种时间
//            updateLastSeedTimeInDB(this.getHexInfoHash().toLowerCase());
//        } catch (Exception e) {
//            // 使用日志框架记录错误
//            logger.error("Failed to update peer stats", e);
//            throw new RuntimeException("Failed to update peer stats", e); // 可根据需求决定是否抛出异常
//        }
//        System.out.println("接收到 peer announce: " + ip + ":" + port + ", uploaded=" + uploaded + ", downloaded=" + downloaded);
//        logger.debug("Peer updated: {}:{} (up={}, down={}, Δup={}, Δdown={})",
//                ip, port, uploaded, downloaded, deltaUpload, deltaDownloaded);
//        return super.update(event,peerId,hexPeerId,ip,port,uploaded,downloaded,left);
//    }
//    // 新增方法：更新 Torrent 的最晚做种时间
//    private void updateLastSeedTimeInDB(String infoHash) {
//        String sql = "UPDATE torrent SET last_seed = now() WHERE info_hash = ?";
//        try (Connection conn = dataSource.getConnection();
//             PreparedStatement stmt = conn.prepareStatement(sql)) {
//            System.out.println("Current info_hash: " + infoHash);
//
//            stmt.setString(1, infoHash);
//            stmt.executeUpdate();
//            System.out.println("更新最后做种时间");
//
//        } catch (SQLException e) {
//            logger.error("Failed to update last_seed_time for info_hash: {}", infoHash, e);
//        }
//    }

//    private void updatePeerStatsInDB(String infoHash, String ip, int port, String peerId, long uploaded, long downloaded,long deltaUpload, long deltaDownload,String passkey) {
//        double shareRatio = downloaded == 0 ? 0.0 : (double) uploaded / downloaded;
//        UserMapper userMapper;
//        String sql = """
//            INSERT INTO peer_stats (info_hash, ip, port, peer_id, uploaded, downloaded, delta_upload, delta_download,share_ratio,passkey)
//            VALUES (?, ?, ?, ?, ?, ?, ?,?,?,?)
//            ON DUPLICATE KEY UPDATE
//                uploaded = VALUES(uploaded),
//                downloaded = VALUES(downloaded),
//                delta_upload = VALUES(delta_upload),
//                delta_download = VALUES(delta_download),
//                share_ratio = VALUES(share_ratio),
//                last_updated = CURRENT_TIMESTAMP,
//                passkey = passkey;
//            """;
//        try (Connection conn = dataSource.getConnection();
//             PreparedStatement stmt = conn.prepareStatement(sql)) {
//
//            stmt.setString(1, infoHash);
//            stmt.setString(2, ip);
//            stmt.setInt(3, port);
//            stmt.setString(4, peerId);
//            stmt.setLong(5, uploaded);
//            stmt.setLong(6, downloaded);
//            stmt.setLong(7, deltaUpload);
//            stmt.setLong(8, deltaDownload);
//            stmt.setDouble(9, shareRatio);
//            //stmt.setString(10,this.passkey);
//            stmt.setString(10,passkey);
//            stmt.executeUpdate();
//            userMapper.incrementUserTraffic(passkey, deltaUpload, deltaDownload);
//
//        } catch (SQLException e) {
//            e.printStackTrace();  // 建议换成日志记录
//        }
//
//    }
}
//package com.pt5.pthouduan.entity;
//
//import com.turn.ttorrent.common.PeerUID;
//import com.turn.ttorrent.common.protocol.AnnounceRequestMessage;
//import com.turn.ttorrent.tracker.TrackedPeer;
//import com.turn.ttorrent.tracker.TrackedTorrent;
//import org.slf4j.Logger;
//import org.slf4j.LoggerFactory;
//
//import javax.sql.DataSource;
//import java.io.UnsupportedEncodingException;
//import java.net.InetSocketAddress;
//import java.nio.ByteBuffer;
//import java.sql.Connection;
//import java.sql.PreparedStatement;
//import java.sql.SQLException;
//import java.util.concurrent.ConcurrentHashMap;
//import java.util.concurrent.ConcurrentMap;
//
//public class TrackeredTorrentWithStats extends TrackedTorrent {
//    private static final Logger logger = LoggerFactory.getLogger(TrackeredTorrentWithStats.class);
//
//    private final ConcurrentMap<PeerUID, long[]> lastStats = new ConcurrentHashMap<>();
//    private final DataSource dataSource;
//    private final String passkey; // 新增passkey字段
//
//    // 修改构造函数，增加passkey参数
//    public TrackeredTorrentWithStats(byte[] infoHash, DataSource datasource, String passkey) {
//        super(infoHash);
//        this.dataSource = datasource;
//        this.passkey = passkey;
//    }
//
//    @Override
//    public TrackedPeer update(AnnounceRequestMessage.RequestEvent event,
//                              ByteBuffer peerId, String hexPeerId,
//                              String ip, int port,
//                              long uploaded, long downloaded, long left)
//            throws UnsupportedEncodingException {
//        PeerUID peerUID = new PeerUID(new InetSocketAddress(ip, port), this.getHexInfoHash());
//
//        // 计算增量流量（防止负数）
//        long[] last = lastStats.getOrDefault(peerUID, new long[]{0L, 0L});
//        long deltaUpload = Math.max(0, uploaded - last[0]);
//        long deltaDownload = Math.max(0, downloaded - last[1]);
//
//        // 更新内存中的最新值
//        lastStats.put(peerUID, new long[]{uploaded, downloaded});
//
//        // 记录到数据库（新增passkey字段）
//        updatePeerStatsInDB(
//                this.getHexInfoHash(),
//                ip, port, hexPeerId,
//                uploaded, downloaded,
//                deltaUpload, deltaDownload
//        );
//
//        logger.debug("Peer updated: {}:{} (up={}, down={}, Δup={}, Δdown={})",
//                ip, port, uploaded, downloaded, deltaUpload, deltaDownload);
//
//        return super.update(event, peerId, hexPeerId, ip, port, uploaded, downloaded, left);
//    }
//
//    private void updatePeerStatsInDB(String infoHash, String ip, int port,
//                                     String peerId, long uploaded, long downloaded,
//                                     long deltaUpload, long deltaDownload) {
//        double shareRatio = (downloaded == 0) ? 0.0 : (double) uploaded / downloaded;
//
//        // 修改SQL，增加passkey字段
//        String sql = """
//            INSERT INTO peer_stats (
//                info_hash, ip, port, peer_id,
//                uploaded, downloaded, delta_upload, delta_download,
//                share_ratio, passkey
//            ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
//            ON DUPLICATE KEY UPDATE
//                uploaded = VALUES(uploaded),
//                downloaded = VALUES(downloaded),
//                delta_upload = VALUES(delta_upload),
//                delta_download = VALUES(delta_download),
//                share_ratio = VALUES(share_ratio),
//                last_updated = CURRENT_TIMESTAMP
//            """;
//
//        try (Connection conn = dataSource.getConnection();
//             PreparedStatement stmt = conn.prepareStatement(sql)) {
//
//            // 设置参数（新增passkey）
//            stmt.setString(1, infoHash);
//            stmt.setString(2, ip);
//            stmt.setInt(3, port);
//            stmt.setString(4, peerId);
//            stmt.setLong(5, uploaded);
//            stmt.setLong(6, downloaded);
//            stmt.setLong(7, deltaUpload);
//            stmt.setLong(8, deltaDownload);
//            stmt.setDouble(9, shareRatio);
//            stmt.setString(10, this.passkey); // 新增passkey
//
//            stmt.executeUpdate();
//
//        } catch (SQLException e) {
//            logger.error("Failed to update peer stats: {}", e.getMessage());
//        }
//    }
//}